﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;



namespace TripLOAMobile.InternalEntities
{
    public partial class ListViewTravelControl : UserControl
    {

        #region Member
        private AnimationControl animation;

        private const int maxTravelForPage = 5;

        private int customHeight;
        private int customWidth;
        private int count;
        private int numberOfPage;
        private int rectangleHeight;
        private int next;
        private int next_Comment;
        private int pointLabel;
        private int pointComment;
        
        private List<UserLink> listTravel;
        private List<string> commentTravel = null;
        private List<string> travel = null;
        private List<int> indexTravel = null;
        private List<bool> arrayBool = null;
        
        private bool load;
        private bool loadComment;
        private bool loadSeparator;
        private bool initializes;
        private bool modify;
        private bool firstLoad;
        private bool notification;
        private bool flag;

        public bool backNot;
        public bool nextNot;
     
        private Color colorSeparator;
        private Color colorOddRows;
        private Color colorEvenRows;

        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="ListViewTravelControl"/> class.
        /// </summary>
        public ListViewTravelControl()
        {
            InitializeComponent();
            this.flag = false;
            this.load = false;
            this.loadComment = false;
            this.modify = false;
            this.initializes = false;
            this.firstLoad = false;
            this.loadSeparator = false;
            this.notification = false;
            this.colorEvenRows = Color.FromArgb(222, 243, 123);
            this.colorOddRows = Color.White;
            this.colorSeparator = Color.GreenYellow;
            this.count = 0;
            this.next = 0;
            this.next_Comment = 0;
            this.listTravel = new List<UserLink>(5);
            this.pointLabel = 7;
            this.pointComment = 23;
            this.numberOfPage = 0;
           



            #region creation of the control for the animation
            animation = new AnimationControl();
            int x = this.Width / 2 - animation.Width / 2;
            int y = this.Height / 2 - animation.Height / 2;
            animation.Location = new Point(x, y);
            this.Controls.Add(animation);
            animation.BringToFront();
            #endregion
        }

        
        public ListViewTravelControl(int ide)
        {
            
            this.colorEvenRows = Color.FromArgb(222, 243, 123);
            this.colorOddRows = Color.White;
            this.colorSeparator = Color.GreenYellow;
            this.count = 0;
            this.next = 0;

            this.notification = true;
            this.flag = false;
            this.load = false;
            this.loadComment = false;
            this.backNot = false;
            this.nextNot = false;

            InitializeComponent();
            
        }


        #region  Region Proprietà

        /// <summary>
        /// Settes the color of the odd rows. 
        /// </summary>
        /// <value>colorOddRows</value>
        public Color SetBackColorOddRows
        {
            set { this.colorOddRows = value; }
        }

        /// <summary>
        /// Settes the color of the even rows.
        /// </summary>
        /// <value>colorEvenRows</value>
        public Color SetBackColorEvenRows
        {
            set { this.colorEvenRows = value; }
        }

        /// <summary>
        /// Insert a separator between the rows.
        /// </summary>
        /// <value>loadSeparator</value>
        public bool Separator
        {
            set { this.loadSeparator = value; }
        }

        /// <summary>
        /// Settes the color of the separator.
        /// </summary>
        /// <value>colorSeparator</value>
        public Color SetColorSeparator
        {
            set { this.colorSeparator = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool TravelsAreBookable
        {
            get;
            set;
        }
        
        /// <summary>
        /// Settes a value that indicate the index of the travels.
        /// </summary>
        /// <value>indexTravel</value>
        private int[] Ide
        {
            set
            {
                if (this.indexTravel == null)
                {
                    this.indexTravel = new List<int>();
                }
                foreach (int ide in value)
                {
                    this.indexTravel.Add(ide);

                }
            }
        }

        /// <summary>
        /// Get the max number of travels contained in a page.
        /// </summary>
        /// <value>maxTravelForPage</value>
        public int MaxTravelsForPage
        {
            get
            {
                return maxTravelForPage;
            }
        }

        /// <summary>
        /// Get the actual number of the page.
        /// </summary>
        /// <value>numberOfPage</value>
        public int ActualNumberPage
        {
            get
            {
                return numberOfPage;
            }

        }

        /// <summary>
        /// Settes the value that indicate the departure and the destination of the travel.
        /// </summary>
        /// <value>travel</value>
        private string[] Links
        {
            set
            {
                if (this.travel == null)
                {
                    this.travel = new List<String>();
                    this.arrayBool = new List<bool>();
                }
                foreach (string str in value)
                {
                    this.travel.Add(str);
                    this.arrayBool.Add(false);

                }


            }
        }

        /// <summary>
        /// Settes the value that indicate the information of the travel.
        /// </summary>
        /// <value>commentTravel</value>
        public string[] Comments
        {

            set
            {
                {
                    if (this.commentTravel == null)
                    {
                        this.commentTravel = new List<String>();
                    }
                    foreach (string str in value)
                    {
                        this.commentTravel.Add(str);
                    }
                }

            }
        }

    
        #endregion

        /// <summary>
        /// Controls if there are travels to view.
        /// </summary>
        /// <returns>true if there are travels to view, false otherwise</returns>
        public bool TravelsInPage()
        {
            if (this.travel.Count > maxTravelForPage)
                return true;
            return false;
        }

        /// <summary>
        /// Controls if the travel's page is full.
        /// </summary>
        /// <returns>true if the page is full, false otherwise</returns>
        public bool PageIsFull()
        {
            if (this.listTravel.Count % 5 == 0)
                return true;
            return false;
        }

        /// <summary>
        /// Controls if all the travels are view.
        /// </summary>
        /// <returns>true if is in the last page, false otherwise</returns>
        public bool NowIsInTheLastPage()
        {
            return (next >= this.travel.Count);
        }

        /// <summary>
        /// Settes the color of even and odd rows, and of the separator. 
        /// </summary>
        /// <param name="evenRows">the color of the even rows</param>
        /// <param name="OddRows">The color of the odd rows</param>
        /// <param name="Separator">The color of the separator</param>
        public void MultiColorsControl(Color evenRows, Color OddRows, Color Separator)
        {
            this.SetBackColorEvenRows = evenRows;
            this.SetBackColorOddRows = OddRows;
            this.SetColorSeparator = Separator;
        }

        /// <summary>
        /// Instances a number of UserLink that can be contained in the ListViewTravelControl
        /// </summary>
        public void InitializesControls()
        {
            for (int i = 0; i < this.listTravel.Capacity; i++)
            {
                this.listTravel.Add(new UserLink());
                this.listTravel.ElementAt(i).Width = this.Width - 6;
                this.listTravel.ElementAt(i).BackColor = (listTravel.Count - 1) % 2 == 0 ? this.colorEvenRows : this.colorOddRows;
                this.listTravel.ElementAt(i).Location = new System.Drawing.Point(4, pointLabel);

                this.Controls.Add(listTravel.ElementAt(i));
                pointLabel += rectangleHeight;
            }

        }

        /// <summary>
        /// Dissectes the control area.
        /// </summary>
        public void Section()
        {
            this.customHeight = 0;
            this.customWidth = this.Width;
            this.rectangleHeight = this.Size.Height / maxTravelForPage;
        }

        /// <summary>
        /// Initializes the names, the information and the identificator of the travels.
        /// </summary>
        /// <param name="travel">The name of the travels</param>
        /// <param name="commentTravel">The information of the travels</param>
        /// <param name="idTravel">The identificator of the travels</param>
        public void Load(string[] travel, string[] commentTravel, int[] idTravel)
        {
            this.Links = travel;
            this.Comments = commentTravel;
            this.Ide = idTravel;
        }

        /// <summary>
        /// View the travels contained in the next page.
        /// </summary>
        public void GoNext()
        {
            this.count = 0;
            this.loadComment = true;
            int app = 0;
            int j = 0;
            int i = 0;

            if (!this.initializes)
            {
                this.InitializesControls();
                this.initializes = true;
            }

            if (count != 0)
                j = count;

            for (i = j; ((i < this.listTravel.Capacity) && (next <= this.travel.Count - 1)); i++)
            {
                this.listTravel.ElementAt(i).Text = travel.ElementAt(next);
                this.listTravel.ElementAt(i).Index = indexTravel.ElementAt(next);

                if (arrayBool[next])
                {
                    this.listTravel.ElementAt(i).ForeColor = Color.Red;
                }
                else
                {
                    this.listTravel.ElementAt(i).ForeColor = Color.Blue;
                }

                this.next++;

            }

            this.addEventClick();
            app = i;
            if (app != 0)
                this.modify = true;

            if (this.modify)
            {
                numberOfPage++;
                while (app < listTravel.Capacity)
                {
                    this.listTravel.ElementAt(app).Text = "";
                    app++;
                    count++;
                }

            }
            this.load = true;
            Invalidate();
            Update();
        }

        /// <summary>
        /// View the travels contained in the page before.
        /// </summary>
        public void GoBack()
        {
            if (this.load)
            {
                this.load = true;
            }
            this.loadComment = false;
            if (next == 0 || next == 5)
            {
                return;
            }

            numberOfPage--;

            if (next % 5 == 0)
            {
                next -= 5;
            }

            while (next % 5 != 0)
            {
                next--;
            }

            if (next != 0)
            {
                next -= 5;
            }
            else
            {
                return;
            }

            for (int j = 0; ((j < this.listTravel.Capacity) && (next <= this.travel.Count - 1)); j++)
            {
                this.listTravel.ElementAt(j).Text = travel[next];
                this.listTravel.ElementAt(j).Index = indexTravel[next];
                if (arrayBool[next])
                {
                    this.listTravel.ElementAt(j).ForeColor = Color.Red;
                }
                else
                {
                    this.listTravel.ElementAt(j).ForeColor = Color.Blue;
                }
                next++;
            }
            this.load = true;
            this.addEventClick();
            Invalidate();
            Update();


        }

        /// <summary>
        /// Load the information of the travels in the current page.
        /// </summary>
        /// <param name="g">The DC to use for drawing</param>
        private void LoadComments(Graphics g)
        {
            if(!firstLoad)
            this.firstLoad = true;

            if (this.flag)
                this.flag = false;

            pointComment = 23;
            int j = 0;
            while ((j < this.listTravel.Capacity) && (next_Comment <= this.commentTravel.Count - 1))
            {
                g.DrawString(this.commentTravel[next_Comment], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, pointComment, this.Width - 2, 25));
                pointComment += rectangleHeight;
                j++;
                next_Comment++;
            }

            if (this.modify)
            {
                while (j < this.listTravel.Capacity)
                {
                    g.DrawString("", new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, pointComment, this.Width - 2, 25));
                    j++;
                }
            }
        }



        #region RegionOfNotification


        /// <summary>
        /// Controls if the notification's page is full.
        /// </summary>
        /// <returns>true if the page is full, false otherwise</returns>
        public bool PageNotificationIsFull()
        {
            if (this.travel.Count % 5 == 0)
                return true;
            return false;
        }

        /// <summary>
        ///  View the notifications contained in the next page.
        /// </summary>
        public void GoNextNotification()
        {
            this.nextNot = true;
            this.backNot = false;
            this.notification = false;
            Invalidate();
            Update();
        }

        /// <summary>
        /// Load the notifications contained in the next page.
        /// </summary>
        /// <param name="g">The DC to use for drawing</param>
        private void NextNotification(Graphics g)
        {
            int point1 = 7;
            int point2 = 23;
            int j = 0;
            bool mod = false;
            while ((next <= this.travel.Count) && (j < maxTravelForPage))
            {
                g.DrawString(travel[next], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point1, this.Width - 2, 25));
                g.DrawString(commentTravel[next], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point2, this.Width - 2, 25));
                point1 += rectangleHeight;
                point2 += rectangleHeight;
                next++;
                j++;
                mod = true;
            }
            if (mod)
            {
                this.numberOfPage++;

                while (j < this.MaxTravelsForPage)
                {
                    g.DrawString("", new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point1, this.Width - 2, 25));
                    g.DrawString("", new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point2, this.Width - 2, 25));
                    point1 += rectangleHeight;
                    point2 += rectangleHeight;
                    j++;
                }
            }

            
        }

        /// <summary>
        /// View the notifications contained in the page before.
        /// </summary>
        public void GoBackNotification()
        {
            this.backNot = true;
            this.nextNot = false;
            this.notification = false;
            Invalidate();
            Update();
        }

        /// <summary>
        /// Load the notifications contained in the page before.
        /// </summary>
        /// <param name="g">The DC to use for drawing</param>
        private void BackNotification(Graphics g)
        {
            int point1 = 7;
            int point2 = 23;
            int j = 0;

            if (next == 0 || next == 5)
            {
                return;
            }

            numberOfPage--;

            if (next % 5 == 0)
            {
                next -= 5;
            }

            while (next % 5 != 0)
            {
                next--;
            }

            if (next != 0)
            {
                next -= 5;
            }
            else
            {
                return;
            }
            while ((next <= this.travel.Count) && (j < maxTravelForPage))
            {
                g.DrawString(travel[next], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point1, this.Width - 2, 25));
                g.DrawString(commentTravel[next], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point2, this.Width - 2, 25));
                point1 += rectangleHeight;
                point2 += rectangleHeight;
                next++;
                j++;
            }

            while (j < this.MaxTravelsForPage)
            {
                g.DrawString("", new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point1, this.Width - 2, 25));
                g.DrawString("", new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point2, this.Width - 2, 25));
                point1 += rectangleHeight;
                point2 += rectangleHeight;
                j++;
            }

        }

        /// <summary>
        /// Initializes the names and the informations of the notifications.
        /// </summary>
        /// <param name="arrayTitle">The names of notifications</param>
        /// <param name="arrayComment">The informations of notifications.</param>
        public void Notifications(string []arrayTitle, string []arrayComment)
        {
            this.Links = arrayTitle;
            this.Comments = arrayComment;
            Invalidate();
            Update();
        }

        /// <summary>
        /// Load the names and the informations of the notifications.
        /// </summary>
        /// <param name="g">The DC to use for drawing</param>
        private void LoadNotifications(Graphics g)
        {
            if (travel != null)
            { 
                int point1 = 7;
                int point2 = 23;
                for (int i = 0; (i < (this.travel.Count)) && (next < maxTravelForPage); i++)
                    {
                        g.DrawString(travel[i], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point1, this.Width - 2, 25));
                        g.DrawString(commentTravel[i], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, point2, this.Width - 2, 25));
                        point1 += rectangleHeight;
                        point2 += rectangleHeight;
                        this.next++;
                    }
            }

        }


        #endregion

        /// <summary>
        /// Load and view the informations of the travel contained in the page.
        /// </summary>
        /// <param name="g">The DC to use for drawing</param>
        private void ModifyComments(Graphics g)
        {
            if (this.firstLoad)
            {
                if (next_Comment == 0 || next_Comment == maxTravelForPage)
                {
                    return;
                }

                if (next_Comment % maxTravelForPage == 0)
                {
                    next_Comment -= maxTravelForPage;
                }

                while (next_Comment % maxTravelForPage != 0)
                {
                    next_Comment--;
                }

                if (next_Comment != 0)
                {
                    next_Comment -= maxTravelForPage;
                }

                else
                {
                    return;
                }

                pointComment = 23;
                int j = 0;

                while ((j < this.listTravel.Capacity) && (next_Comment <= this.commentTravel.Count - 1))
                {
                    g.DrawString(this.commentTravel[next_Comment], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, pointComment, this.Width - 2, 25));
                    pointComment += rectangleHeight;
                    j++;
                    next_Comment++;
                }
            }

            if (this.flag)
            {
                pointComment = 23;
                int j = 0;

                while ((j < this.listTravel.Capacity) && (next_Comment <= this.commentTravel.Count - 1))
                {
                    g.DrawString(this.commentTravel[next_Comment], new Font(FontFamily.GenericMonospace, 9, FontStyle.Regular), new SolidBrush(Color.Black), new RectangleF(4, pointComment, this.Width - 2, 25));
                    pointComment += rectangleHeight;
                    j++;
                    next_Comment++;
                    this.flag = false;
                }
            }

        }

        /// <summary>
        /// Add the event Click to the UserLink instantiate in the control.
        /// </summary>
        private void addEventClick()
        {
            int clickOn = this.next;
            if (clickOn <= 5)
            {
                for (int i = 0; i < clickOn; i++)
                {
                    listTravel[i].Click += new System.EventHandler(this.link_Label_Click);
                }
            }
            else
            {
                while (clickOn >= 5)
                {
                    clickOn = next - 5;
                }
                for (int i = clickOn; i < this.listTravel.Count; i++)
                {
                    listTravel[i].Click -= new System.EventHandler(this.link_Label_Click);
                }

            }
        }

      
        #region override methods

      
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (this.Height != 240)
            { this.Height = 240; }
            if (this.Width != 210)
            { this.Width = 210; }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
            Rectangle r;

            if (this.load || this.flag || this.notification || this.nextNot || this.backNot)
            {
              
                using (SolidBrush b = new SolidBrush(this.colorEvenRows))
                {
                    r = new Rectangle(0, this.customHeight, this.Width, this.rectangleHeight);
                    this.customHeight += 2 * this.rectangleHeight;
                    g.FillRectangle(b, r);

                    r = new Rectangle(0, this.customHeight, this.Width, this.rectangleHeight);
                    this.customHeight += 2 * this.rectangleHeight;
                    g.FillRectangle(b, r);

                    r = new Rectangle(0, this.customHeight, this.Width, this.rectangleHeight);
                    g.FillRectangle(b, r);

                }


                using (SolidBrush b = new SolidBrush(this.colorOddRows))
                {
                    this.customHeight = this.rectangleHeight;

                    r = new Rectangle(0, this.customHeight, this.Width, this.rectangleHeight);
                    this.customHeight += 2 * this.rectangleHeight;
                    g.FillRectangle(b, r);

                    r = new Rectangle(0, this.customHeight, this.Width, this.rectangleHeight);
                    g.FillRectangle(b, r);


                }


                using (SolidBrush b = new SolidBrush(this.colorSeparator))
                {

                    this.customHeight = this.rectangleHeight;
                    r = new Rectangle(0, 0, this.Width, 2);
                    g.FillRectangle(b, r);
                    for (int i = 0; i < 4; i++)
                    {
                        r = new Rectangle(0, (this.customHeight - 1), this.Width, 2);
                        g.FillRectangle(b, r);
                        this.customHeight += this.rectangleHeight;
                    }
                    r = new Rectangle(0, (this.customHeight - 2), this.Width, 2);
                    g.FillRectangle(b, r);
                    this.customHeight += this.rectangleHeight;

                    r = new Rectangle(0, 0, 2, this.Height);
                    g.FillRectangle(b, r);
                    r = new Rectangle(this.Width - 2, 0, 2, this.Height);
                    g.FillRectangle(b, r);


                }


                using (SolidBrush b = new SolidBrush(this.colorOddRows))
                {
                    this.customHeight = this.rectangleHeight;
                    r = new Rectangle(2, 2, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    r = new Rectangle(2, this.customHeight - 1 - 5, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    this.customHeight += rectangleHeight;
                    r = new Rectangle(2, this.customHeight + 1, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    this.customHeight += rectangleHeight;
                    r = new Rectangle(2, this.customHeight - 1 - 5, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    this.customHeight += rectangleHeight;
                    r = new Rectangle(2, this.customHeight + 1, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    this.customHeight += rectangleHeight;
                    r = new Rectangle(2, this.customHeight - 2 - 5, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                }

                using (SolidBrush b = new SolidBrush(this.colorEvenRows))
                {
                    this.customHeight = this.rectangleHeight;
                    r = new Rectangle(2, this.customHeight + 1, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    this.customHeight += this.rectangleHeight;
                    r = new Rectangle(2, this.customHeight - 1 - 5, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    this.customHeight += this.rectangleHeight;
                    r = new Rectangle(2, this.customHeight + 1, this.Width - 4, 5);
                    g.FillRectangle(b, r);
                    this.customHeight += this.rectangleHeight;
                    r = new Rectangle(2, this.customHeight - 1 - 5, this.Width - 4, 5);
                    g.FillRectangle(b, r);

                }
                this.load = false;
                if (this.flag)
                {
                    if (this.next_Comment % maxTravelForPage == 0)
                    {
                        this.next_Comment -= maxTravelForPage;
                    }

                    while (this.next_Comment % maxTravelForPage != 0)
                    {
                        this.next_Comment--;
                    }
                    this.firstLoad = false;
                }
                
            }
            if (this.notification)
            {
                this.LoadNotifications(g);
            }
            else if (this.backNot)
            {
                this.BackNotification(g);
            }
            else if(this.nextNot)
            {
                this.NextNotification(g);
            }


            if (loadComment)
                LoadComments(g);
            else
                ModifyComments(g);
            this.customHeight = 0;
            this.modify = false;
        }

        #endregion

        /// <summary>
        /// Stops the animation.
        /// This animation is used to simulated the waiting time
        /// </summary>
        private void stopAnimation()
        {
            this.animation.StopAnimation();
           
        }

        /// <summary>
        /// Starts the animation.
        /// This animation is used to simulated the waiting time
        /// </summary>
        private void startAnimation()
        {
            this.animation.StartAnimation();
        }

        /// <summary>
        /// Occurs when an UserLink in the control  is clicked.
        /// </summary>
        private void link_Label_Click(object sender, EventArgs e)
        {
            this.startAnimation();
            UserLink app = (UserLink)sender;
            app.ForeColor = Color.Red;
            int index = (numberOfPage - 1) * 5;
            while (!((app.Index) == this.indexTravel.ElementAt(index)))
                index++;
            
            this.arrayBool[index] = true;
            ShowDetails detForm = new ShowDetails(indexTravel[index], TravelsAreBookable);
            Welcome.formBuffer.Add(detForm,"ShowDetails");
            this.flag = true;
            this.stopAnimation();
            detForm.ShowDialog();
            detForm.Dispose();

        }
    }
}


 